/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina;

import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.juli.logging.Log;

import javax.management.ObjectName;
import java.beans.PropertyChangeListener;
import java.io.File;


/**
 * A <b>Container</b> is an object that can execute requests received from
 * a client, and return responses based on those requests.  A Container may
 * optionally support a pipeline of Valves that process the request in an
 * order configured at runtime, by implementing the <b>Pipeline</b> interface
 * as well.
 * <p>
 * Containers will exist at several conceptual levels within Catalina.  The
 * following examples represent common cases:
 * <ul>
 * <li><b>Engine</b> - Representation of the entire Catalina servlet engine,
 *     most likely containing one or more subcontainers that are either Host
 *     or Context implementations, or other custom groups.
 * <li><b>Host</b> - Representation of a virtual host containing a number
 *     of Contexts.
 * <li><b>Context</b> - Representation of a single ServletContext, which will
 *     typically contain one or more Wrappers for the supported servlets.
 * <li><b>Wrapper</b> - Representation of an individual servlet definition
 *     (which may support multiple servlet instances if the servlet itself
 *     implements SingleThreadModel).
 * </ul>
 * A given deployment of Catalina need not include Containers at all of the
 * levels described above.  For example, an administration application
 * embedded within a network device (such as a router) might only contain
 * a single Context and a few Wrappers, or even a single Wrapper if the
 * application is relatively small.  Therefore, Container implementations
 * need to be designed so that they will operate correctly in the absence
 * of parent Containers in a given deployment.
 * <p>
 * A Container may also be associated with a number of support components
 * that provide functionality which might be shared (by attaching it to a
 * parent Container) or individually customized.  The following support
 * components are currently recognized:
 * <ul>
 * <li><b>Loader</b> - Class loader to use for integrating new Java classes
 *     for this Container into the JVM in which Catalina is running.
 * <li><b>Logger</b> - Implementation of the <code>log()</code> method
 *     signatures of the <code>ServletContext</code> interface.
 * <li><b>Manager</b> - Manager for the pool of Sessions associated with
 *     this Container.
 * <li><b>Realm</b> - Read-only interface to a security domain, for
 *     authenticating user identities and their corresponding roles.
 * <li><b>Resources</b> - JNDI directory context enabling access to static
 *     resources, enabling custom linkages to existing server components when
 *     Catalina is embedded in a larger server.
 * </ul>
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 */
public interface Container extends Lifecycle {
    /**
     * 当容器添加子容器时触发该事件，并通知容器监听器
     */
    public static final String ADD_CHILD_EVENT = "addChild";
    /**
     * 当容器添加 Valve 时触发该事件，并通知容器监听器
     */
    public static final String ADD_VALVE_EVENT = "addValve";
    /**
     * 当容器移除子容器时触发该事件，并通知容器监听器
     */
    public static final String REMOVE_CHILD_EVENT = "removeChild";
    /**
     * 当容器移除 Valve 时触发该事件，并通知容器监听器
     */
    public static final String REMOVE_VALVE_EVENT = "removeValve";


    /**
     * 获取与容器关联的 Log 组件
     *
     * @return
     */
    public Log getLogger();

    /**
     * 获取与容器关联的 Log 组件名
     */
    public String getLogName();


    /**
     * 获取容器注册到 JMX 的对象名
     */
    public ObjectName getObjectName();


    /**
     * 获取容器注册到 JVM 时指定的 Domain
     */
    public String getDomain();


    /**
     * 计算用于注册到 JMX 中时使用的 Key Property 字符串
     */
    public String getMBeanKeyProperties();

    /**
     * 获取与容器关联的 Pipeline 组件
     */
    public Pipeline getPipeline();

    /**
     * 获取与容器关联的 Cluster 罪案
     */
    public Cluster getCluster();

    /**
     * 设置与容器关联的 Cluster 组件
     */
    public void setCluster(Cluster cluster);


    /**
     * 获取容器执行周期性调度的延迟时间
     */
    public int getBackgroundProcessorDelay();

    /**
     * 设置容器执行周期性调度的延迟时间
     */
    public void setBackgroundProcessorDelay(int delay);


    /**
     * 获取容器名
     */
    public String getName();

    /**
     * 设置容器名
     */
    public void setName(String name);

    /**
     * 获取父容器
     */
    public Container getParent();

    /**
     * 设置父容器
     */
    public void setParent(Container container);

    /**
     * 获取设置的父类加载器
     */
    public ClassLoader getParentClassLoader();

    /**
     * 设置父类加载器
     */
    public void setParentClassLoader(ClassLoader parent);

    /**
     * 获取容器关联的 Realm 组件
     */
    public Realm getRealm();


    /**
     * 设置容器关联的 Realm 组件
     */
    public void setRealm(Realm realm);

    /**
     * 周期性执行方法，例如可以通过该方法重新加载容器
     */
    public void backgroundProcess();

    /**
     * 添加子容器
     */
    public void addChild(Container child);

    /**
     * 添加容器监听器
     */
    public void addContainerListener(ContainerListener listener);


    /**
     * 添加属性改变时调用的监听器，这个 PropertyChangeListener 接口为 JDK 类库中的定义
     * 即使用 JDK 自带的 java.beans 包下定义好的监听器和事件对象，并没有自定义
     */
    public void addPropertyChangeListener(PropertyChangeListener listener);

    /**
     * 通过容器名获取子容器
     */
    public Container findChild(String name);

    /**
     * 获取所有子容器
     */
    public Container[] findChildren();

    /**
     * 获取所有容器的监听器
     */
    public ContainerListener[] findContainerListeners();


    /**
     * 移除指定的子容器
     */
    public void removeChild(Container child);


    /**
     * 移除指定的容器监听器
     */
    public void removeContainerListener(ContainerListener listener);


    /**
     * 移除指定的监听属性变化的监听器
     */
    public void removePropertyChangeListener(PropertyChangeListener listener);


    /**
     * 通知所有容器监听器，type 为容器事件类型字符串对象，data 为一起发送的数据
     */
    public void fireContainerEvent(String type, Object data);


    /**
     * 记录客户端访问容器的日志。request 为 Tomcat 实现了 J2EE 的 HttpServletRequest 实例
     * response 为 Tomcat 实现了 J2EE 的 HttpServletResponse 实例，time 为访问时间
     * useDefault 表明是否应该记录在引擎组件默认的访问日志中
     */
    public void logAccess(Request request, Response response, long time,
                          boolean useDefault);


    /**
     * 获取与当前容器关联的记录访问日志的组件
     */
    public AccessLog getAccessLog();


    /**
     * 获取用于启动或者停止子容器的线程数，可以通过该线程数让子容器并行启动或停止
     */
    public int getStartStopThreads();


    /**
     * 设置用于启动或停止子容器的线程数
     */
    public void setStartStopThreads(int startStopThreads);


    /**
     * 获取 CATALINA_BASE 的 File 文件对象
     * CATALINA_BASE 表示包含配置文件，log日志文件，部署的应用程序和其他运行时所需资源的路径
     * 通常将 CATALINA_BASE 和 CATALINA_HOME 指定为同一个目录
     * 但如果在单机上运行多个 Tomcat，可以将 CATALINA_BASE 设置为不同实例的目录，这样就可以多个 Tomcat 实例共享同一个 Tomcat 静态文件
     * 即 CATALINA_HOME 下的 jar 包等，而动态文件和不同配置可以通过 CATALINA_BASE 配置
     */
    public File getCatalinaBase();


    /**
     * 获取 CATALINA_HOME 的 File 对象。表示 Tomcat 的安装根路径
     */
    public File getCatalinaHome();
}
